home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
kernel
/
dev
/
devDiskStats.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-18
|
10KB
|
372 lines
/*
* devDiskStats.c --
*
* Routines supporting statistics on Sprite Disk usage.
*
* Copyright 1989 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/devDiskStats.c,v 9.6 91/09/10 18:19:34 rab Exp $ SPRITE (Berkeley)";
#endif /* not lint */
#include <sprite.h>
#include <stdio.h>
#include <sync.h>
#include <sysStats.h>
#include <devDiskStats.h>
#include <user/fs.h>
#include <stdlib.h>
#include <list.h>
#include <bstring.h>
#include <string.h>
/*
* The disk stats modules cleans a linked list of registers disk to implment
* the Idle counts of devices. This list is composed of devices.
*/
typedef struct Device {
List_Links links; /* Used by the List_Links library routines.*/
Boolean (*idleCheck) _ARGS_ ((ClientData, DevDiskStats *));
/* Routine to check device's state. */
ClientData clientData; /* ClientData argument to idleCheck. */
int type; /* Fs_Device type of this disk. */
int unit; /* Fs_Device unit of this disk. */
DevDiskStats devDiskStats;
int refCount; /* # of times we've attached partition. */
} Device;
/*
* If idleCheck functions are kept in a list pointed to by deviceListHdr and
* protected by deviceListMutex. The variable initialized set to TRUE
* indicates the list has been initialized.
*/
static Sync_Semaphore deviceListMutex = Sync_SemInitStatic("devDiskStatMutex");
static List_Links deviceListHdr;
static Boolean initialized = FALSE;
/*
*----------------------------------------------------------------------
*
* Dev_GatherDiskStats --
*
* Determine which disks are idle. This routine should be called
* periodically to obtain an estimate of the idle percentage of
* a disk.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
Dev_GatherDiskStats()
{
register Device *devicePtr;
/*
* If any device has been registered do an idle check on all
* registered devices.
*/
if (initialized) {
MASTER_LOCK(&deviceListMutex);
LIST_FORALL(&deviceListHdr, (List_Links *) devicePtr) {
register Sys_DiskStats *stats =
&(devicePtr->devDiskStats.diskStats);
stats->numSamples++;
if (devicePtr->idleCheck == (Boolean((*) _ARGS_ ((ClientData,
DevDiskStats *)))) NIL) {
stats->idleCount++; /* No disk anymore. */
} else if ((devicePtr->idleCheck)(devicePtr->clientData,
&(devicePtr->devDiskStats))) {
stats->idleCount++;
}
}
MASTER_UNLOCK(&deviceListMutex);
}
}
/*
*----------------------------------------------------------------------
*
* Dev_GetDiskStats --
*
* Return statistics about the different disks.
*
* Results:
* Number of statistics entries returned.
*
* Side effects:
* Entries in *diskStatPtr filled in.
*
*----------------------------------------------------------------------
*/
int
Dev_GetDiskStats(diskStatArr, numEntries)
Sys_DiskStats *diskStatArr; /* Where to store the disk stats. */
int numEntries; /* The number of elements in diskStatArr. */
{
Device *devicePtr;
int index;
MASTER_LOCK(&deviceListMutex);
/*
* Return Sys_DiskStats for all registers devices being careful not to
* overrun the callers buffer.
*/
index = 0;
if (initialized) {
LIST_FORALL(&deviceListHdr, (List_Links *) devicePtr) {
if (index >= numEntries) {
break;
}
diskStatArr[index] = devicePtr->devDiskStats.diskStats;
index += 1;
}
}
MASTER_UNLOCK(&deviceListMutex);
return index;
}
/*
*----------------------------------------------------------------------
*
* DevRegisterDisk--
*
* Register a disk with the disk stat module so that its idle
* percentage can be computed from period sampling and its diskStats
* structure may available to the Dev_GetDiskStats routine.
*
* Results:
* The initialized DevDiskStats structure for the device.
*
* Side effects:
* The idleCheck function will be called when periodcally and should
* return TRUE if the disk is idle. It is should be declared as follows:
*
* Boolean idleCheck(clientData, diskStatsPtr)
* ClientData clientData -- The clientData argument passed
* to DevRegisterDevice.
* DevDiskStats *diskStatsPtr -- Ptr to disk stats.
*
*----------------------------------------------------------------------
*/
DevDiskStats *
DevRegisterDisk(devicePtr, deviceName, idleCheck, clientData)
Fs_Device *devicePtr; /* Fs_Device for disk. */
char *deviceName; /* Printable name for this device. */
Boolean (*idleCheck) _ARGS_ ((ClientData, DevDiskStats *));
/* Function returning TRUE if the device
* is idle. */
ClientData clientData; /* ClientData argument passed to idleCheck
* to indicate which device. */
{
Device *newDevice, *devPtr;
Boolean found = FALSE;
/*
* Allocated, initialized, and add to the callback list a Device structure
* for this device.
*/
newDevice = (Device *) malloc(sizeof(Device));
List_InitElement((List_Links *) newDevice);
newDevice->idleCheck = idleCheck;
newDevice->clientData = clientData;
newDevice->type = devicePtr->type;
newDevice->unit = devicePtr->unit;
bzero((char *) &(newDevice->devDiskStats), sizeof(DevDiskStats));
Sync_SemInitDynamic(&(newDevice->devDiskStats.mutex), "DevDiskStats");
(void) strncpy(newDevice->devDiskStats.diskStats.name, deviceName,
SYS_DISK_NAME_LENGTH);
MASTER_LOCK(&deviceListMutex);
if (!initialized) {
List_Init(&deviceListHdr);
initialized = TRUE;
}
LIST_FORALL(&deviceListHdr, (List_Links *) devPtr) {
if ((devPtr->unit == devicePtr->unit) &&
(devPtr->type == devicePtr->type)) {
found = TRUE;
break;
}
}
if (found) {
devPtr->idleCheck = idleCheck;
devPtr->clientData = clientData;
} else {
List_Insert((List_Links *) newDevice, LIST_ATREAR(&deviceListHdr));
devPtr = newDevice;
}
devPtr->refCount++;
MASTER_UNLOCK(&deviceListMutex);
if (found) {
free((char *)newDevice);
}
return &(devPtr->devDiskStats);
}
/*
*----------------------------------------------------------------------
*
* DevDiskUnregister--
*
* Unregister a disk with the disk stat module.
*
* Results:
* None.
*
* Side effects:
* The idleCheck function will cease calculating for this disk.
*
*----------------------------------------------------------------------
*/
void
DevDiskUnregister(diskStatsPtr)
DevDiskStats *diskStatsPtr;
{
Device *devPtr;
Boolean found = FALSE;
/*
* Allocated, initialized, and add to the callback list a Device structure
* for this device.
*/
MASTER_LOCK(&deviceListMutex);
if (!initialized) {
MASTER_UNLOCK(&deviceListMutex);
return;
}
LIST_FORALL(&deviceListHdr, (List_Links *) devPtr) {
if (diskStatsPtr == &(devPtr->devDiskStats)) {
found = TRUE;
break;
}
}
if (found) {
/*
* For stupid reasons to do with spritemon, we're not allowed to
* free up this space. Once a disk is noticed by the stat stuff, the
* user interface doesn't want to see it go away.
*/
devPtr->refCount--;
if (devPtr->refCount == 0) {
devPtr->idleCheck = (Boolean((*) _ARGS_ ((ClientData,
DevDiskStats *)))) NIL;
devPtr->clientData = (ClientData) NIL;
}
}
MASTER_UNLOCK(&deviceListMutex);
return;
}
/*
* Temporary call-back for printing io statistics for recovery.
*/
Timer_QueueElement ioStatElement;
Boolean getIOStats = FALSE;
/*ARGSUSED*/
void
DevPrintIOStats(time, clientData)
Timer_Ticks time;
ClientData clientData;
{
Sys_DiskStats diskStats[10];
int numStats;
int i;
/* print stuff */
numStats = Dev_GetDiskStats(diskStats, 10 * sizeof (Sys_DiskStats));
printf("IO STATS:\n");
for (i = 0; i < numStats; i++) {
printf("name: %s\n", diskStats[i].name);
printf("controllerID: %d\n", diskStats[i].controllerID);
printf("numSamples: %d\n", diskStats[i].numSamples);
printf("idleCount: %d\n", diskStats[i].idleCount);
printf("diskReads: %d\n", diskStats[i].diskReads);
printf("diskWrites: %d\n", diskStats[i].diskWrites);
}
printf("\n");
if (getIOStats) {
Timer_ScheduleRoutine(&ioStatElement, TRUE);
}
return;
}
/*
*----------------------------------------------------------------------
*
* Dev_StartIOStats --
*
* Start up the kernel's periodic printing of io stats.
* Temporary routine for recovery statistics.
*
* Results:
* None.
*
* Side effects:
* Call-back routine scheduled.
*
*----------------------------------------------------------------------
*/
void
Dev_StartIOStats()
{
ioStatElement.routine = DevPrintIOStats;
ioStatElement.clientData = 0;
ioStatElement.interval = timer_IntOneSecond * 10;
getIOStats = TRUE;
Timer_ScheduleRoutine(&ioStatElement, TRUE);
return;
}
/*
*----------------------------------------------------------------------
*
* Dev_StopIOStats --
*
* Stop the kernel's periodic printing of io stats.
* Temporary routine for recovery statistics.
*
* Results:
* None.
*
* Side effects:
* Call-back routine descheduled.
*
*----------------------------------------------------------------------
*/
void
Dev_StopIOStats()
{
getIOStats = FALSE;
(void) Timer_DescheduleRoutine(&ioStatElement);
return;
}